/*!
 Temelia - Algorithms performance tests.

 Copyright (C) 2008 Ceata (http://cod.ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "include/performance.hpp"
#include "include/testutil.hpp"

#include <algorithm>
#include <vector>

extern "C"
{
#include <temelia/algorithms.h>
}

static void my_free_key(void *data, void *context)
{
	// Actually no call is done, because I want to reuse the collection
	// for more than one test
	//free(data);
}

static void temelia_map(int n)
{
	// Tested function
	map(default_collection, n, my_key_at, my_free_key, NULL);
}

static void temelia_binary_search(int n)
{
	int x;

	for (int i = 0; i < n; i++)
		default_collection[i][0] = i;

	for (int i = 0; i < n / 2; i++)
		binary_search(default_collection, n, default_collection[i], my_key_at,
				int_compare, NULL);

	for (int i = 0; i < n / 4; i++)
	{
		x = -i - 1;
		binary_search(default_collection, n, &x, my_key_at, int_compare, NULL);

		x = n + i;
		binary_search(default_collection, n, &x, my_key_at, int_compare, NULL);
	}
}

static int my_filter(void *key, void *context)
{
	// nothing special
	return rand() % 2;
}

static void then_function(void *key, void *context)
{
	// nothing
}

static void else_function(void *key, void *context)
{
	// nothing
}

static void temelia_filter(int n)
{
	filter(default_collection, n, my_key_at, my_filter, then_function,
			else_function, NULL, NULL, NULL);
}

static void myfunction(int *i)
{
	// don't free the pointers, because I want to recycle them :-)
	//free(i);
}

static void stl_map(int n)
{
	std::vector<int *> myvector(default_collection, default_collection + n);

	// Tested function
	for_each(myvector.begin(), myvector.end(), myfunction);
}

static void stl_binary_search(int n)
{
	int x;
	std::vector<int *> vect(default_collection, default_collection + n);

	for (int i = 0; i < n / 2; i++)
		std::binary_search(vect.begin(), vect.end(), vect[i], stl_int_compare);

	for (int i = 0; i < n / 4; i++)
	{
		x = -i - 1;
		std::binary_search(vect.begin(), vect.end(), &x, stl_int_compare);

		x = n + i;
		binary_search(vect.begin(), vect.end(), &x, stl_int_compare);
	}
}

void TemeliaPerformance::pt_algorithms(void)
{
	TestUnit testUnit("algorithms");

	GENERATE_TEMELIA_TEST(testUnit, "map", map);
	GENERATE_TEMELIA_TEST(testUnit, "binary_search", binary_search);
	GENERATE_TEMELIA_TEST(testUnit, "filter", filter);

	GENERATE_STL_TEST(testUnit, "map", map);
	GENERATE_STL_TEST(testUnit, "binary_search", binary_search);

	testUnit.write(fout);
}
